#include "StdAfx.h"
#include "MediaBuffer.h"
#include "MediaFrame.h"


CMediaBuffer::CMediaBuffer(EMediaType e)
	:	m_eMediaType(e)	
	,	m_NullEvent(TRUE)
	,	m_ValidEvent(TRUE)
	,	m_llStart(0), m_llStop(0)
{
}

CMediaBuffer::~CMediaBuffer(void)
{
	DeinitBuffer();
}


BOOL CMediaBuffer::InitBuffer(INT size /* = 30 */)
{
	while(m_qTotal.size() < (deque<CMediaFrame*>::size_type)size){
		CMediaFrame* p = NULL;
		if( m_eMediaType ==	MEDIA_TYPE_AUDIO ){
			p = (CMediaFrame*)new CAudioFrame;
		}else if( m_eMediaType == MEDIA_TYPE_VIDEO ){
			p = (CMediaFrame*)new CVideoFrame;
		}
		if(!p) return FALSE;
		m_qTotal.push_back(p);		
		
	}
	
	{
		CAutoLock lock(&m_csNull);	
		if(!m_qJustNull.empty())m_qJustNull.clear();
		m_qJustNull.insert(m_qJustNull.begin(), m_qTotal.begin(), m_qTotal.end());	
		for (deque<CMediaFrame*>::iterator it = m_qJustNull.begin(); it < m_qJustNull.end(); it++)
		{
			(*it)->SetEOS(FALSE);
		}
	}
	m_NullEvent.Set();

	{	
		CAutoLock lock1(&m_csValid);
		if(!m_qValidData.empty()) m_qValidData.clear();
	}
	m_ValidEvent.Reset();
	
	return TRUE;	
}

void CMediaBuffer::DeinitBuffer()
{	
	m_NullEvent.Set();
	m_ValidEvent.Set();
	Sleep(500);
	deque<CMediaFrame*>::iterator it;
	for (it = m_qTotal.begin(); it < m_qTotal.end(); it++)
	{
		CMediaFrame* p = *it;
		delete p;
		p = NULL;
	}
}

static int g = 0;
CMediaFrame* CMediaBuffer::GetNullFrame()
{
	if( !m_NullEvent.Wait(500)) return NULL;
	if(m_qJustNull.size() < 1 ) 
		return NULL;

	CAutoLock lock1(&m_csNull);
	CMediaFrame* p = m_qJustNull.front();
	g++;
	m_qJustNull.pop_front();
	if(m_qJustNull.size() < 1) 
		m_NullEvent.Reset();
	return p;
}


CMediaFrame* CMediaBuffer::GetValidFrame()
{
	if(!m_ValidEvent.Wait(500)) return NULL;
	if(m_qValidData.size() < 1) return NULL;

	CAutoLock lock1(&m_csValid);
	CMediaFrame* p = m_qValidData.front();
	m_qValidData.pop_front();

	if(m_qValidData.size() < 1){
		m_ValidEvent.Reset();
	}else{
		CMediaFrame* pp = m_qValidData.front();
		if(pp) pp->GetTime(m_llStart, m_llStop);
	}
	
	return p;
}

VOID CMediaBuffer::PushNullFrame(CMediaFrame* p)
{
	if(!p) return;

	CAutoLock lock1(&m_csNull);
	m_qJustNull.push_back(p);
	m_NullEvent.Set();
}

VOID CMediaBuffer::PushValidFrame(CMediaFrame* p)
{
	if(!p) return;

	CAutoLock lock1(&m_csValid);
	m_qValidData.push_back(p);
	m_ValidEvent.Set();
}

BOOL CMediaBuffer::GetFirstFrameTime(LONGLONG& llStart, LONGLONG& llStop)
{
	llStart = m_llStart;
	llStop  = m_llStop;
	return TRUE;
}








